home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Compendium Deluxe 2
/
LSD and 17bit Compendium Deluxe - Volume II.iso
/
a
/
prog
/
asmsrc
/
thesource-7.lha
/
Source
/
DefFunc.lha
/
DefFunc
/
dfcparse.y
< prev
next >
Wrap
Text File
|
1993-12-14
|
9KB
|
329 lines
/****************************************************************
*
* Copyright (c) 1993 Ke Jin
*
* Permission to use, copy, modify, and distribute
* this software and its documentation without fee
* is granted, provided that the author's name and
* this copyright notice are retained.
*
* ------------------------------------------------------------
*
* dfcparse.y -- the yacc file of defunc parser
*
* public function : yyparse();
* yyinit();
* getparsetree();
*
* public variable : exparserror;
*
* private function : addnode();
* yyreverse();
* yyerror();
* yywrap();
*
* private variable : yyparsetree;
* yytreesize;
* newnode;
*
****************************************************************/
%{
#include <stdio.h>
#include <malloc.h>
#include <math.h>
#include <string.h>
#include "dfctree.h"
#include "dfcsymtable.h"
char* exparserror;
static char ermsgbuff[128];
static Node* yyparsetree;
static int yytreesize;
static Node newnode;
#if NeedFunctionPrototypes
int yyparse(void);
static int yyreverse(void);
#else
extern int yyparse();
extern int yyreverse();
#endif
#if NeedFunctionPrototypes
static int addnode(Node *ptr)
#else
static int addnode(ptr)
Node *ptr;
#endif
{
yytreesize++;
if(yytreesize==1)
{
yyparsetree = (Node*)malloc(sizeof(Node));
}
else
{
yyparsetree = (Node*)realloc((Node*)yyparsetree,
yytreesize*sizeof(Node));
}
if(yyparsetree==0)
{
perror("malloc/realloc in addnode()");
exit(1);
}
if(yyparsetree == 0)
{
fprintf(stderr, "fail to allocate memory in add node\n");
exit(1);
}
/* yyparsetree[yytreesize-1] = *ptr; */
memcpy(yyparsetree+yytreesize-1, ptr, sizeof(Node));
return yytreesize-1;
};
%}
%union {
int nodeidx;
int argidx;
double value;
double (*fnctptr)();
char name[32];
}
%token <value> CONST /* constant */
%token <argidx> ARG /* function arguments */
%token <fnctptr> FNCT /* intrinsic function */
%token <name> SYM /* new symbol */
%type <nodeidx> expr /* function expression */
%left '-' '+'
%left '*' '/'
%left SIG
%right '^'
%% /* ------------------- syntax rules ------------------------ */
input : '\n' {
return 0;
}
| ';' {
return 0;
}
| expr '\n' {
return yyreverse();
}
| expr ';' {
return yyreverse();
}
| error '\n' {
return -1;
}
;
expr : CONST {
newnode.type = const_node;
newnode.content.value = $1;
$$ = addnode(&newnode);
}
| SYM {
sprintf(ermsgbuff,
"unknow token \"%s\"", $1);
exparserror = ermsgbuff;
return -1;
}
| CONST '(' ')' {
newnode.type = const_node;
newnode.content.value = $1;
$$ = addnode(&newnode);
}
| CONST '(' expr ')' {
newnode.type = const_node;
newnode.content.value = $1;
$$ = addnode(&newnode);
}
| ARG {
newnode.type = arg_node;
newnode.content.argidx = $1;
$$ = addnode(&newnode);
}
| FNCT '(' expr ')' {
newnode.type = simplex_fnct_node;
newnode.content.fnctptr = $1;
newnode.right = $3;
$$ = addnode(&newnode);
}
| FNCT '(' expr ',' expr ')' {
newnode.type = duplex_fnct_node;
newnode.content.fnctptr = $1;
newnode.left = $3;
newnode.right= $5;
$$ = addnode(&newnode);
}
| FNCT '(' expr ',' expr ',' expr ')' {
exparserror
= "not support triplex function yet";
return -1;
}
| expr '+' expr {
newnode.type = binary_op_node;
newnode.content.op = op_sum;
newnode.left = $1;
newnode.right= $3;
$$ = addnode(&newnode);
}
| expr '-' expr {
newnode.type = binary_op_node;
newnode.content.op = op_sub;
newnode.left = $1;
newnode.right= $3;
$$ = addnode(&newnode);
}
| expr '*' expr {
newnode.type = binary_op_node;
newnode.content.op = op_mul;
newnode.left = $1;
newnode.right= $3;
$$ = addnode(&newnode);
}
| expr '/' expr {
newnode.type = binary_op_node;
newnode.content.op = op_div;
newnode.left =$1;
newnode.right=$3;
$$ = addnode(&newnode);
}
| '-' expr %prec SIG {
newnode.type = unary_op_node;
newnode.content.op = op_neg;
newnode.right = $2;
$$ = addnode(&newnode);
}
| '+' expr %prec SIG {
$$ = $2;
}
| expr '^' expr {
newnode.type = duplex_fnct_node;
newnode.content.fnctptr = pow;
newnode.left = $1;
newnode.right= $3;
$$ = addnode(&newnode);
}
| '(' expr ')' {
$$ = $2;
}
;
%% /* --------------------------------------------------------- */
#include "dfcscan.h"
#if NeedFunctionPrototype
int yyinit(char* expr)
#else
int yyinit(expr)
char *expr;
#endif
{
initargu();
yyexpr = expr;
yyexprlen = strlen(yyexpr);
yypos = 0;
yytreesize = 0;
return 0;
};
#if NeedFunctionPrototypes
static int yyreverse(void)
#else
static int yyreverse()
#endif
/* yyparse() use a LALR(1) bottom-up algorithem to construct the
parse tree. Thus the result tree is upsetdown, i.e. the root
is place on the end of the yyparsetree[]. yyreverse make it
in right order, i.e. yyparsetree[0] be the root */
{
int i;
Node* buff;
if(yytreesize==0) return 0;
buff = (Node*)malloc(sizeof(Node)*yytreesize);
if(buff==0)
{
perror("malloc in reverse()");
exit(1);
}
for(i=0; i<yytreesize; i++) /* reverse */
{
/* buff[i] = yyparsetree[yytreesize-1-i]; */
memcpy(buff+i, yyparsetree+yytreesize-1-i, sizeof(Node));
buff[i].left = yytreesize - 1 - buff[i].left;
buff[i].right= yytreesize - 1 - buff[i].right;
}
for(i=0; i<yytreesize; i++) /* put it back */
{
yyparsetree[i] = buff[i];
}
free(buff);
return yytreesize;
};
#if NeedFunctionPrototypes
int getparsetree(Node* buff)
#else
int getparsetree(buff)
Node* buff;
#endif
/* copy the parse into buff */
{
int i;
for(i=0; i<yytreesize; i++)
{
buff[i] = yyparsetree[i];
}
return yytreesize;
};
#if NeedFunctionPrototypes
static void yyerror(char* s)
#else
static yyerror(s)
char *s;
#endif
{
exparserror=s;
};
#if NeedFunctionPrototypes
static int yywrap(void)
#else
static int yywrap()
#endif
{
return 1;
};